<template>
  <div class="fc-style">
    <a-layout class="fc-container">
      <a-layout-content class="fc-main">
        <a-layout>
          <a-layout-sider theme="light" :width="250" class="cg-container">
            <div
              class="flex items-center justify-center h-full flex-col text-[18px] text-[#ccc] text-center leading-6"
            >
              <Icon icon="ant-design:stop-twotone" size="28" />
              <div>系统功能页面不允许操作组件</div>
              <div>只能针对组件进行排版布局及样式调整</div>
            </div>
          </a-layout-sider>
          <a-layout class="center-container">
            <a-layout-content id="layoutId" :class="{ 'widget-empty': widgetForm.list }">
              <MobileLayout>
                <template #designContent>
                  <AntdWidgetForm
                    ref="widgetFormRef"
                    v-model:widgetForm="widgetForm"
                    v-model:widgetFormSelect="widgetFormSelect"
                  />
                </template>
              </MobileLayout>
            </a-layout-content>
          </a-layout>
          <a-layout-sider theme="light" class="widget-config-container" :width="320">
            <a-layout class="layout-height">
              <a-tabs
                v-model:activeKey="configTab"
                centered
                style="margin-bottom: 8px; background: #fff; height: 100%"
              >
                <a-tab-pane key="widget" :tab="t('组件属性')">
                  <a-tabs v-model:activeKey="chooseTab" centered v-if="widgetFormSelect">
                    <a-tab-pane key="property" :tab="t('属性设置')">
                      <div class="widget-none" v-if="['grid'].includes(widgetFormSelect.type)">
                        <SvgIcon name="exclamation" :size="44" />
                        <p>{{ t(widgetFormSelect.label + '不允许配置属性设置') }}</p>
                      </div>
                      <PropertyOption
                        v-model:select="widgetFormSelect"
                        :widgetForm="widgetForm"
                        v-else
                      />
                    </a-tab-pane>

                    <a-tab-pane key="regular" :tab="t('正则校验')">
                      <div
                        class="widget-none"
                        v-if="noConfigRegularSetting.includes(widgetFormSelect.type)"
                      >
                        <SvgIcon name="exclamation" :size="44" />
                        <p>{{ t(widgetFormSelect.label + '无法配置正则检验') }}</p>
                      </div>
                      <RegularSetting v-model:select="widgetFormSelect" v-else />
                    </a-tab-pane>
                  </a-tabs>
                  <div class="widget-none" v-else>
                    <SvgIcon name="tool" :size="44" />
                    <p>{{ t('点击组件后再查看组件属性') }}</p>
                  </div>
                </a-tab-pane>
                <!-- <a-tab-pane key="form" :tab="t('表单属性')">
                  <AntdFormConfig v-model:config="widgetForm.config" />
                </a-tab-pane> -->
              </a-tabs>
            </a-layout>
          </a-layout-sider>
        </a-layout>
      </a-layout-content>

      <a-modal
        v-model:visible="uploadJsonVisible"
        :title="t('导入JSON')"
        :width="800"
        @ok="handleUploadJson"
        :okText="t('确认')"
        :cancelText="t('取消')"
      >
        <a-alert
          type="info"
          :message="t('JSON格式如下，直接复制生成的json覆盖此处代码点击确定即可')"
          style="margin-bottom: 10px"
        />
        <CodeEditor v-model:value="jsonEg" language="json" />
      </a-modal>

      <PreviewDrawer @register="registerDrawer" />

      <a-modal
        v-model:visible="generateJsonVisible"
        :title="t('生成JSON')"
        :okText="t('复制')"
        :cancelText="t('取消')"
        :width="800"
        @ok="handleCopyClick(generateJsonTemplate)"
      >
        <CodeEditor :value="generateJsonTemplate" language="json" readonly />
      </a-modal>

      <a-modal
        v-model:visible="dataJsonVisible"
        :title="t('获取数据')"
        :okText="t('复制')"
        :cancelText="t('取消')"
        :width="800"
        @ok="handleCopyClick(dataJsonTemplate)"
      >
        <CodeEditor :value="dataJsonTemplate" language="json" readonly />
      </a-modal>

      <a-modal
        v-model:visible="dataCodeVisible"
        :title="t('生产代码')"
        :okText="t('复制')"
        :cancelText="t('取消')"
        :width="800"
        @ok="handleCopyClick(dataCodeTemplate)"
      >
        <a-tabs type="card" v-model:activeKey="codeLanguage" :tabBarStyle="{ margin: 0 }">
          <a-tab-pane tab="Vue Component" :key="codeType.Vue">
            <CodeEditor :value="dataCodeTemplate" language="html" readonly />
          </a-tab-pane>
          <a-tab-pane tab="HTML" :key="codeType.Html">
            <CodeEditor :value="dataCodeTemplate" language="html" readonly />
          </a-tab-pane>
        </a-tabs>
      </a-modal>
    </a-layout>
  </div>
</template>

<script lang="ts">
  import {
    defineComponent,
    reactive,
    PropType,
    toRefs,
    watchEffect,
    provide,
    watch,
    inject,
  } from 'vue';
  import { message } from 'ant-design-vue';
  import { cloneDeep, merge, debounce } from 'lodash-es';
  import { CodeEditor } from '/@/components/CodeEditor';

  import AntdWidgetForm from './AntdWidgetForm.vue';
  import PropertyOption from './PropertyOption.vue';
  import RegularSetting from '/@/components/Designer/src/components/componentProperty/RegularSetting.vue';

  //import AntdFormConfig from './AntdFormConfig.vue';

  import * as antd from '/@/components/Designer/src/types';
  import { copy } from '/@/utils';
  import generateCode from '/@/components/Designer/src/util/generateCode';
  import { WidgetForm, CodeType, PlatformType } from '/@/components/Designer/src/types';
  import PreviewDrawer from '/@/components/Designer/src/components/PreviewDrawer.vue';
  import { useDrawer } from '/@/components/Drawer';
  import { GeneratorConfig } from '/@/model/generator/generatorConfig';
  import {
    noConfigComponentEvent,
    noConfigRegularSetting,
    noHaveTableAndField,
  } from '/@/components/Designer/src/types';
  import MobileLayout from '../../components/mobileLayout.vue';
  import { SvgIcon, Icon } from '/@/components/Icon';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { useI18n } from '/@/hooks/web/useI18n';
  const { t } = useI18n();
  export default defineComponent({
    name: 'AntdDesignForm',
    components: {
      Icon,
      CodeEditor,
      AntdWidgetForm,
      PreviewDrawer,
      // AntdFormConfig,
      PropertyOption,
      RegularSetting,
      SvgIcon,
      MobileLayout,
    },
    props: {
      preview: {
        type: Boolean,
        default: true,
      },

      generateJson: {
        type: Boolean,
        default: true,
      },
      uploadJson: {
        type: Boolean,
        default: true,
      },
      clearable: {
        type: Boolean,
        default: true,
      },
      basicFields: {
        type: Array as PropType<Array<string>>,
        default: () => ['input', 'textarea', 'password', 'number', 'richtext-editor', 'auto-code'],
      },
      advanceFields: {
        type: Array as PropType<Array<string>>,
        default: () => [
          'select',
          'cascader',
          'associate-select',
          'multiple-popup',
          'associate-popup',
          'area',
          'checkbox',
          'radio',
          'switch',
          'slider',
          'time',
          'time-range',
          'date',
          'date-range',
          'rate',
          'picker-color',
          'upload',
          'image',
          'button',
          'map',
          'qrcode',
        ],
      },
      layoutFields: {
        type: Array as PropType<Array<string>>,
        default: () => ['form', 'one-for-one', 'title', 'grid', 'tab', 'card', 'divider'],
      },
      workFlowFields: {
        type: Array as PropType<Array<string>>,
        default: () => ['opinion'],
      },
      infoFields: {
        type: Array as PropType<Array<string>>,
        default: () => ['info', 'organization', 'user'],
      },
      financeFields: {
        type: Array as PropType<Array<string>>,
        default: () => ['computational', 'money-chinese'],
      },
    },
    setup(props) {
      const state = reactive({
        antd,
        codeType: CodeType,
        widgetForm: undefined as any,
        widgetFormSelect: undefined as any,
        generateFormRef: null as any,
        configTab: 'widget',
        chooseTab: 'property',
        previewVisible: false,
        uploadJsonVisible: false,
        dataJsonVisible: false,
        dataCodeVisible: false,
        generateJsonVisible: false,
        generateCodeVisible: false,
        generateJsonTemplate: JSON.stringify(antd.widgetForm, null, 2),
        dataJsonTemplate: '',
        dataCodeTemplate: '',
        codeLanguage: CodeType.Vue,
        jsonEg: JSON.stringify(antd.widgetForm, null, 2),
        componentGroupKey: ['1', '2', '3', '4', '5', '6'],
        componentList: [
          {
            title: t('输入型组件'),
            fields: props.basicFields,
            list: antd.basicComponents,
          },
          {
            title: t('选择型组件'),
            fields: props.advanceFields,
            list: antd.advanceComponents,
          },
          {
            title: t('布局型组件'),
            fields: props.layoutFields,
            list: antd.layoutComponents,
          },
          {
            title: t('工作流组件'),
            fields: props.workFlowFields,
            list: antd.workFlowComponents,
          },
          {
            title: t('组织架构'),
            fields: props.infoFields,
            list: antd.infoComponents,
          },
          {
            title: t('财务组件'),
            fields: props.financeFields,
            list: antd.financeComponents,
          },
        ],
      });
      state.widgetForm = inject('widgetForm');
      const generatorConfig = inject<GeneratorConfig>('generatorConfig') as GeneratorConfig;
      const { notification } = useMessage();

      //注入数据
      provide('state', state);

      const handleUploadJson = () => {
        try {
          setJson(JSON.parse(state.jsonEg));
          state.uploadJsonVisible = false;
          message.success(t('上传成功'));
        } catch (error) {
          message.error(t('上传失败'));
        }
      };

      const handleCopyClick = (text: string) => {
        copy(text);
        message.success(t('Copy成功'));
      };

      const handleGetData = () => {
        state.generateFormRef.getData().then((res: any) => {
          state.dataJsonTemplate = JSON.stringify(res, null, 2);
          state.dataJsonVisible = true;
        });
      };

      const handleGenerateJson = () => {
        (state.generateJsonTemplate = JSON.stringify(state.widgetForm, null, 2)) &&
          (state.generateJsonVisible = true);
      };

      const handleGenerateCode = () => {
        state.codeLanguage = CodeType.Vue;
        state.dataCodeVisible = true;
      };

      watchEffect(() => {
        if (state.dataCodeVisible) {
          state.dataCodeTemplate = generateCode(
            state.widgetForm,
            state.codeLanguage,
            PlatformType.Antd,
          )!;
        }
      });

      const handleClearable = () => {
        state.widgetForm.list = [];
        merge(state.widgetForm, JSON.parse(JSON.stringify(antd.widgetForm)));
        state.widgetFormSelect = undefined;
      };

      const handleReset = () => state.generateFormRef.reset();

      const getJson = () => state.widgetForm;

      const setJson = (json: WidgetForm) => {
        state.widgetForm.list = [];
        merge(state.widgetForm, json);
        if (json.list.length) {
          state.widgetFormSelect = json.list[0];
        }
      };
      const designType = inject<string>('designType');

      const handlerPreview = () => {
        if (designType === 'data' && hasNoBindTableOrField(state.widgetForm.list)) {
          notification.error({
            message: t('提示'),
            description: t('请先将组件绑定表和字段'),
          }); //提示消息
        } else {
          openDrawer(true, getJson());
        }
      };

      const hasNoBindTableOrField = (component) => {
        const hasSubComponent = ['tab', 'grid', 'card', 'one-for-one', 'form'];
        return component?.some((info) => {
          if (hasSubComponent.includes(info.type!)) {
            if (info.type === 'form' || info.type === 'one-for-one') {
              return hasNoBindTableOrField(info.children);
            } else {
              return info.layout?.some((childInfo) => {
                return hasNoBindTableOrField(childInfo.list);
              });
            }
          } else {
            if (info.type === 'time-range' || info.type === 'date-range') {
              return !info.bindTable || !info.bindStartTime || !info.bindEndTime;
            }
            return noHaveTableAndField.includes(info.type)
              ? false
              : !info.bindTable || !info.bindField;
          }
        });
      };

      const getTemplate = (codeType: CodeType) =>
        generateCode(state.widgetForm, codeType, PlatformType.Antd);

      const clear = () => handleClearable();

      //这里使用了防抖 包裹  因为监听 state.widgetForm 会执行2次
      watch(
        () => state.widgetForm,
        debounce((val) => {
          generatorConfig.formJson = cloneDeep(val);
        }, 50),
        { deep: true },
      );

      //注册抽屉 获取外部操作抽屉得方法
      const [registerDrawer, { openDrawer }] = useDrawer();

      return {
        ...toRefs(state),
        handleUploadJson,
        handleCopyClick,
        handleGetData,
        handleGenerateJson,
        handleGenerateCode,
        handleClearable,
        handleReset,
        getJson,
        setJson,
        getTemplate,
        clear,
        noConfigComponentEvent,
        noConfigRegularSetting,
        handlerPreview,
        registerDrawer,
        t,
      };
    },
  });
</script>
<style scoped lang="less">
  .fc-style {
    height: 100%;
  }

  .layout-height {
    height: 100%;
    background-color: #f0f2f5;
  }

  :deep(.design-bg-box) {
    .design-box {
      padding-top: 62px;
      padding-bottom: 22px;
      background: #fff;

      .design-content-box {
        padding: 0 80px;
      }
    }
  }

  :deep(.ant-collapse-content-box) {
    padding: 0 0 5px;
  }

  :deep(.ant-tabs) {
    height: 100%;
  }

  //:deep(.ant-tabs-content-holder) {
  //overflow-y: auto;
  //padding: 0 10px 10px 0;
  //}

  :deep(.ant-tabs-content-top) {
    height: 100%;
  }

  :deep(.ant-radio-group) {
    display: flex;

    .ant-radio-button-wrapper {
      display: flex;
      justify-content: center;
      align-items: center;
      flex: 1;
      padding: 3px 0 !important;
    }
  }

  .widget-none {
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;

    p {
      margin: 10px;
      color: #cecece;
    }
  }

  :deep(.ant-tabs-nav) {
    margin-bottom: 8px;
  }

  :deep(.ant-form-item) {
    margin-bottom: 10px;
  }

  :deep(.ant-radio-group-small .ant-radio-button-wrapper) {
    padding: 3px 10px;
    box-sizing: content-box;
  }

  .cg-container {
    margin-bottom: 8px;
    overflow-y: scroll;
    box-sizing: border-box;
  }

  .fc-container {
    height: 100%;
  }

  .ant-layout.ant-layout-has-sider {
    height: 100%;
  }

  .center-container {
    height: calc(100% - 8px);
    background-color: #fff;
    padding-bottom: 20px;
    box-sizing: border-box;
    border-left: 8px solid #f0f2f5;
    border-right: 8px solid #f0f2f5;
  }
</style>
